#ifndef __WEAPONS_H
#define __WEAPONS_H

#include "Soldier Control.h"

INT16 MAXCHANCETOHIT;
INT16 BAD_DODGE_POSITION_PENALTY;

INT16 GUN_BARREL_RANGE_BONUS;

// Special deaths can only occur within a limited distance to the target
INT16 MAX_DISTANCE_FOR_MESSY_DEATH;
// If you do a lot of damage with a close-range shot, instant kill
INT16 MIN_DAMAGE_FOR_INSTANT_KILL;
// If you happen to kill someone with a close-range shot doing a lot of damage to the head, head explosion
INT16 MIN_DAMAGE_FOR_HEAD_EXPLOSION;
// If you happen to kill someone with a close-range shot doing a lot of damage to the chest, chest explosion
// This value is lower than head because of the damage bonus for shooting the head
INT16 MIN_DAMAGE_FOR_BLOWN_AWAY;
// If you happen to hit someone in the legs for enough damage, REGARDLESS of distance, person falls down
// Leg damage is halved for these purposes
INT16 MIN_DAMAGE_FOR_AUTO_FALL_OVER;

// short range at which being prone provides to hit penalty when shooting standing people
INT16 MIN_PRONE_RANGE;

// can't miss at this range?
INT16 POINT_BLANK_RANGE;

INT16 BODY_IMPACT_ABSORPTION;

#define BUCKSHOT_SHOTS 9

INT16 MIN_MORTAR_RANGE;			// minimum range of a mortar

// WEAPON CLASSES
enum
{
	NOGUNCLASS,
	HANDGUNCLASS,
	SMGCLASS,
	RIFLECLASS,
	MGCLASS,
	SHOTGUNCLASS,
	KNIFECLASS,
	MONSTERCLASS,
	MOUNTEDCLASS,
	NUM_WEAPON_CLASSES
};

// exact gun types
/*enum
{
	NOT_GUN = 0,
	GUN_PISTOL,
	GUN_M_PISTOL,
	GUN_SMG,
	GUN_RIFLE,
	GUN_SN_RIFLE,
	GUN_AS_RIFLE,
	GUN_LMG,
	GUN_SHOTGUN
};*/


// ARMOUR CLASSES
enum 
{
	ARMOURCLASS_HELMET,
	ARMOURCLASS_VEST,
	ARMOURCLASS_LEGGINGS,
	ARMOURCLASS_PLATE,
	ARMOURCLASS_MONST,
	ARMOURCLASS_VEHICLE
};

// Warning: There is a table in weapons.c that indexes using these enumberations...
// BurstSndStrings[]....
enum
{
	NOAMMO = 0,
	AMMOSW,
	AMMO9,
	AMMO45,
	AMMO357,
	AMMO12G,
	AMMOCAWS,
	AMMO545,
	AMMO556,
	AMMO762N,
	AMMO762W,
	AMMO47,
	AMMO57,
	AMMOMONST,
	AMMOROCKET,
	AMMODART,
	AMMOFLAME,
	AMMO762R,
};

enum
{
	AMMO_REGULAR = 0,
	AMMO_HP,
	AMMO_AP,
	AMMO_SUPER_AP,
	AMMO_BUCKSHOT,
	AMMO_FLECHETTE,
	AMMO_GRENADE,
	AMMO_MONSTER,
	AMMO_KNIFE,
	AMMO_HE,
	AMMO_HEAT,
	AMMO_SLEEP_DART,
	AMMO_FLAME,
};

enum
{
	EXPLOSV_NORMAL,
	EXPLOSV_STUN,
	EXPLOSV_TEARGAS,
	EXPLOSV_MUSTGAS,
	EXPLOSV_FLARE,
	EXPLOSV_NOISE,
	EXPLOSV_SMOKE,
  EXPLOSV_CREATUREGAS,
};

INT16 AMMO_DAMAGE_ADJ_BUCKSHOT_DIVIDER;
#define AMMO_DAMAGE_ADJUSTMENT_BUCKSHOT( x ) (x / AMMO_DAMAGE_ADJ_BUCKSHOT_DIVIDER)
INT16 NUM_BUCKSHOT_PELLETS;

// one quarter of punching damage is "real" rather than breath damage
INT16 PUNCH_REAL_DAMAGE_PORTION;

INT16 AIM_BONUS_SAME_TARGET;      // chance-to-hit bonus (in %)
INT16 AIM_BONUS_PER_AP;      // chance-to-hit bonus (in %) for aim
INT16 AIM_BONUS_CROUCHING;
INT16 AIM_BONUS_PRONE;
INT16 AIM_BONUS_TWO_HANDED_PISTOL;
INT16 AIM_BONUS_FIRING_DOWN;
INT16 AIM_PENALTY_ONE_HANDED_PISTOL;
INT16 AIM_PENALTY_DUAL_PISTOLS;
INT16 AIM_PENALTY_SMG;
INT16 AIM_PENALTY_GASSED;
INT16 AIM_PENALTY_GETTINGAID;
INT16 AIM_PENALTY_PER_SHOCK;      // 5% penalty per point of shock
INT16 AIM_BONUS_TARGET_HATED;
INT16 AIM_BONUS_PSYCHO;
INT16 AIM_PENALTY_TARGET_BUDDY;
INT16 AIM_PENALTY_BURSTING;
INT16 AIM_PENALTY_GENTLEMAN;
INT16 AIM_PENALTY_TARGET_CROUCHED;
INT16 AIM_PENALTY_TARGET_PRONE;
INT16 AIM_PENALTY_BLIND;
INT16 AIM_PENALTY_FIRING_UP;

//<SB>
#define MAX_WEAPON_TYPE_NAME			64

#define MAX_WEAPON_CLASSES			32
#define MAX_WEAPON_CLASS_ALIAS	32
#define WEAPON_CLASS_TAG			_T("WEAPONCLASS")
#define MAX_WEAPON_SOUND_PATH		64

#define MAX_WEAPON_TYPES			256
#define WEAPON_TYPE_TAG				_T("WEAPON")

#define MAX_CALIBERS					256
#define MAX_CALIBER_NAME			32
#define CALIBER_TAG					_T("CALIBER")

#define MAX_AMMOTYPES				256
#define MAX_AMMOTYPE_NAME			32
#define AMMOTYPE_TAG					_T("AMMOTYPE")

#define MAX_MAGAZINES				256
#define MAGAZINE_TAG					_T("MAGAZINE")

#define MAX_ARMOUR_CLASSES			32
#define MAX_ARMOUR_CLASS_ALIAS	32
#define ARMOUR_CLASS_TAG			_T("ARMOURCLASS")

#define MAX_ARMOUR_TYPES			256
#define ARMOUR_TYPE_TAG				_T("ARMOURTYPE")

#define MAX_EXPLOSIVE_CLASSES			32
#define MAX_EXPLOSIVE_CLASS_ALIAS	32
#define EXPLOSIVE_CLASS_TAG			_T("EXPLOSIVECLASS")

#define MAX_EXPLOSIVE_TYPES			256
#define EXPLOSIVE_TYPE_TAG				_T("EXPLOSIVETYPE")

typedef struct
{
	UINT8 ubBullets;
	UINT8 ubPenalty;
	UINT16 usROF;
} FIREMODE;

typedef struct
{
 UINT8	ubWeaponClass;             // handgun/shotgun/rifle/knife
 UINT8	ubCalibre;	               // type of ammunition needed
 UINT8	ubReadyTime;               // APs to ready/unready weapon
 UINT8	ubShotsPer4Turns;          // maximum (mechanical) firing rate
 UINT8	ubBulletSpeed;             // bullet's travelling speed
 UINT8	ubImpact;		               // weapon's max damage impact (size & speed)
 UINT8	ubDeadliness;							 // comparative ratings of guns
 UINT8	ubMagSize;			//default/fixed magazine capacity
 UINT16	usRange;
 UINT16	usReloadDelay;
 WCHAR	tsWeaponType[MAX_WEAPON_TYPE_NAME]; // item box description string
 TCHAR	tsSound[MAX_WEAPON_SOUND_PATH];		// single shot sound
 TCHAR	tsBurstSound[MAX_WEAPON_SOUND_PATH];
 TCHAR	tsReloadSound[MAX_WEAPON_SOUND_PATH];
 TCHAR	tsLocknLoadSound[MAX_WEAPON_SOUND_PATH];
 UINT8	ubAttackVolume;
 UINT8	ubHitVolume;
 UINT8	ubReloadAPs;		// APs to reload gun
 UINT8	ubSelfloading;		// self-loading, if not - locknload after single shot 
 UINT8	ubFeedType;			// standard of detachable magazine/clip feed
 UINT8	ubFixedMag;			// fixed magazine - reload with clips or 1 by 1 cartridge
 UINT8	ubLocknLoadAPs;	// APs to Lock'n'Load
 UINT8	ubBoltHoldOpen;	// Bolt-hold-open device, for selfloading gun only
 FIREMODE mode[3];			// available weapon fire modes
 UINT32	uiShotSpread;		// spread of group of projectiles, depend of barrel
} WEAPONTYPE;


extern int SBBurstLength(SOLDIERTYPE * pSoldier, UINT8 ubSlot);
extern int SBGetMainCalFireModesNumber( SOLDIERTYPE *pSoldier, UINT8 ubHandPos );

//#define BURST_LENGTH(pSldr) \
//(Weapon[Item[pSldr->usAttackingWeapon].ubClassIndex ].usROF*(pSldr->ubBurstAP+1)/(12*pSldr->bInitialActionPoints))

#define BURST_LENGTH(pSldr) SBBurstLength( (pSldr), (pSldr)->ubAttackingHand)
#define BURST_LENGTH_IN_SLOT(pSldr,slot) SBBurstLength( (pSldr), (slot) )

//#define BURST_LENGTH_IN_SLOT(pSldr,slot) \
//(Weapon[Item[pSldr->inv[slot].usItem].ubClassIndex ].usROF*(pSldr->ubBurstAP+1)/(12*pSldr->bInitialActionPoints))
//</SB>

typedef struct
{
	TCHAR alias[MAX_CALIBER_NAME];
	TCHAR sound[MAX_WEAPON_SOUND_PATH];
	TCHAR burstsound[MAX_WEAPON_SOUND_PATH];
	INT32	iPower;
} CaliberStruct;

typedef struct
{
	UINT8	ubCalibre;
	UINT8 ubMagSize;
	UINT8	ubAmmoType;
	UINT8	ubFeedType;
	UINT8 ubClip;
} MAGTYPE;

typedef struct
{
	UINT8	ubArmourClass;
	UINT8	ubProtection;
	UINT8	ubDegradePercent;
} ARMOURTYPE;

typedef struct
{
	UINT8		ubType;					// type of explosive
	UINT8		ubDamage;				// damage value
	UINT8		ubStunDamage;		// stun amount / 100
	UINT8		ubRadius;				// radius of effect
	UINT8		ubVolume;				// sound radius of explosion
	UINT8		ubVolatility;		// maximum chance of accidental explosion
	UINT8		ubAnimationID;	// Animation enum to use
} EXPLOSIVETYPE;

//GLOBALS

extern CaliberStruct gCalibers[MAX_CALIBERS];
extern WEAPONTYPE Weapon[ MAX_WEAPON_TYPES ];
extern ARMOURTYPE Armour[ MAX_ARMOUR_TYPES ];
extern MAGTYPE Magazine[];
extern EXPLOSIVETYPE Explosive[ MAX_EXPLOSIVE_TYPES ];
//SB
typedef struct
{
	TCHAR alias[MAX_AMMOTYPE_NAME];
	UINT32 armormultiplier;
	UINT32 armordivider;
	UINT32 damagemultiplier;
	UINT32 damagedivider;
	UINT32 structuremultiplier;
	UINT32 structuredivider;
} AMMOTYPE;

extern AMMOTYPE gAmmoTypes[MAX_AMMOTYPES];

extern INT8 EffectiveArmour( OBJECTTYPE * pObj );
extern INT8 ArmourVersusExplosivesPercent( SOLDIERTYPE * pSoldier );
extern BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo );
extern void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 sBreathLoss, UINT16 usDirection, INT16 sXPos, INT16 sYPos, INT16 sZPos, INT16 sRange , UINT8 ubAttackerID, BOOLEAN fHit, UINT8 ubSpecial, UINT8 ubHitLocation );
extern void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT8 bWeaponStatus, UINT8 ubAttackerID, UINT16 sXPos, INT16 sYPos, INT16 sZPos, UINT16 usStructureID, INT32 iImpact, BOOLEAN fStopped );
extern void WindowHit( INT16 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce );
extern INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, INT16 sHitBy, UINT8 * pubSpecial );
extern BOOLEAN InRange( SOLDIERTYPE *pSoldier, INT16 sGridNo );
extern void ShotMiss( UINT8 ubAttackerID, INT32 iBullet );
extern UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime, UINT8 ubAimPos );
extern UINT32 AICalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime, UINT8 ubAimPos );
extern UINT32 CalcChanceToPunch(SOLDIERTYPE *pAttacker, SOLDIERTYPE * pDefender, UINT8 ubAimTime);
extern UINT32 CalcChanceToStab(SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, UINT8 ubAimTime);
UINT32 CalcChanceToSteal(SOLDIERTYPE *pAttacker, SOLDIERTYPE * pDefender, UINT8 ubAimTime);
extern void ReloadWeapon( SOLDIERTYPE *pSoldier, UINT8 ubHandPos );

//SB
//extern BOOLEAN IsGunBurstCapable( SOLDIERTYPE *pSoldier, UINT8 ubHandPos , BOOLEAN fNotify );
extern int SBFindLongestBurstMode( SOLDIERTYPE *pSoldier, UINT8 ubHandPos , BOOLEAN fNotify );

extern INT32 CalcBodyImpactReduction( UINT8 ubAmmoType, UINT8 ubHitLocation );
extern INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, UINT8 ubAmmoType );
extern INT8 ArmourPercent( SOLDIERTYPE * pSoldier );

extern void GetTargetWorldPositions( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo, FLOAT *pdXPos, FLOAT *pdYPos, FLOAT *pdZPos );

extern BOOLEAN	OKFireWeapon( SOLDIERTYPE *pSoldier );
extern BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier );

extern INT32 CalcMaxTossRange( SOLDIERTYPE * pSoldier, UINT16 usItem, BOOLEAN fArmed );
extern UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAimTime, UINT8 ubAimPos );

extern void ChangeWeaponMode( SOLDIERTYPE * pSoldier );
//SB
extern void ResetWeaponMode( SOLDIERTYPE * pSoldier );

extern BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo, BOOLEAN fStealing );

void DishoutQueenSwipeDamage( SOLDIERTYPE *pQueenSoldier );

INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BOOLEAN fBladeAttack );

UINT16 GunRange( OBJECTTYPE * pObj );

// SB
int GetWeaponIniSettings(TCHAR * tsIniPath, HWND hConsole);

#endif